package com.sale.system.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sale.common.core.utils.StringUtils;
import com.sale.common.mybatis.core.page.PageQuery;
import com.sale.common.mybatis.core.page.TableDataInfo;
import com.sale.system.api.domain.vo.SysAuditHistoryVo;
import com.sale.system.domain.SysAppConfigNode;
import com.sale.system.domain.SysExamine;
import com.sale.system.domain.dto.SysAppConfigNodeDto;
import com.sale.system.domain.dto.SysAuditHistoryDto;
import com.sale.system.domain.dto.SysExamineDto;
import com.sale.system.domain.dto.SysTheDropDto;
import com.sale.system.mapper.*;
import com.sale.system.service.ISysExamineService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @Author hl
 **/
@Slf4j
@RequiredArgsConstructor
@Service
public class SysExamineServiceImpl implements ISysExamineService {

    private final SysExamineMapper sysExamineMapper;

    private final SysAppConfigNodeMapper sysAppConfigNodeMapper;

    private final SysTheAlarmMapper sysTheAlarmMapper;

    private final SysMenuMapper sysMenuMapper;

    private final SysAuditHistoryMapper sysAuditHistoryMapper;

    private final SysRoleMapper sysRoleMapper;

    private final SysUserMapper sysUserMapper;


    /**
     * 分页查询审核信息
     *
     * @param sysExamine
     * @return TableDataInfo
     */
    @Override
    public TableDataInfo<SysExamine> selectExamineList(SysExamine sysExamine, PageQuery pageQuery) {
        Page<SysExamine> page = sysExamineMapper.selectPageExamineList(pageQuery.build(), this.buildQueryWrapper(sysExamine));
        return TableDataInfo.build(page);
    }

    /**
     * 新增审核信息
     *
     * @param sysExamine
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertExamine(SysExamine sysExamine) throws Exception {
        int in = sysExamineMapper.appCheckUniqueness(sysExamine.getExamineCode());
        if (in > 0) {
            throw new SQLException("配置编码不能重复");
        }
       // sysExamine.setDeptId(SecurityUtils.getDeptId());
        List<String> appList = sysExamine.getExamineButtonIds();
        String sy = "";
        for (String code :
            appList) {
            sy += code + ",";
        }
        sy = sy.substring(0, sy.length() - 1);
        sysExamine.setButtonIds(sy);
        int ins = sysExamineMapper.insertExamine(sysExamine);
        if (ins == 0) {
            throw new SQLException("抛出异常");
        }
        return theNodeConfig(sysExamine);
    }

    /**
     * 删除审核信息
     *
     * @param examineId
     * @return int
     */
    @Override
    public int deleteExamine(String examineId) throws SQLException {
        String[] arr = examineId.split(",");
        int in = sysExamineMapper.deleteSysAppConfig(arr);
        if (in == 0) {
            throw new SQLException("抛出异常");
        }
        in = sysExamineMapper.deleteSysAppNoteConfig(arr);
        return in;
    }

    @Override
    public SysExamineDto getExamineInfo(long examineId) {
        SysExamineDto sysExamineDto = sysExamineMapper.selectExamineList(examineId);;
        List<SysAppConfigNodeDto> nodeList = sysAppConfigNodeMapper.getAppNodeInfo(sysExamineDto.getExamineId());
        for (SysAppConfigNodeDto sy :
            nodeList) {
            //取出用户id
            String userId = sy.getNodeUserId();
            String[] str = userId.split(",");
            String userName = sysUserMapper.selectUserByIdStr(str);
            String[] nameS = userName.split(",");
            String[] userIdS = userId.split(",");
            List<SysTheDropDto> listThe = new ArrayList<SysTheDropDto>();
            for (int i = 0; i < nameS.length; i++) {
                SysTheDropDto st = new SysTheDropDto();
                st.setLabel(nameS[i]);
                st.setValue(userIdS[i]);
                listThe.add(st);
            }
            sy.setNodeUser(listThe);
            String roleId = sy.getNodeRoleId();
            String[] roleIdX = roleId.split(",");
            String roleName = sysRoleMapper.selectRoleNameService(roleIdX);
            if (!StringUtils.isEmpty(roleName)) {
                String[] roleIdS = roleId.split(",");
                String[] roleNameS = roleName.split(",");
                List<SysTheDropDto> listThe2 = new ArrayList<SysTheDropDto>();
                for (int j = 0; j < roleIdS.length; j++) {
                    SysTheDropDto st = new SysTheDropDto();
                    st.setValue(roleIdS[j]);
                    st.setLabel(roleNameS[j]);
                    listThe2.add(st);
                }
                sy.setNodeRole(listThe2);
                sy.setUserAndRole(userName + "," + roleName);
            }
            sy.setUserAndRole(userName);
        }
        sysExamineDto.setAuditNodeCode(nodeList);
        String str1 = sysExamineDto.getButtonIds();
        String[] str = str1.split(",");
        List<String> klList = new ArrayList<>();
        for (String kl :
            str) {
            klList.add(kl);
        }
        sysExamineDto.setExamineButtonIds(klList);
        return sysExamineDto;
    }


    /**
     * 修改审核信息
     *
     * @param sysExamine
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateSysExamineEdit(SysExamine sysExamine) throws Exception {
        sysExamineMapper.updateExamineEdit(sysExamine);
        sysExamineMapper.deleteExamineOnBy(sysExamine.getExamineId());
        return theNodeConfig(sysExamine);
    }

    /**
     * 根据按钮权限码返回审核信息
     * <p>
     * ryTask.ryNoParams
     *
     * @param sysAuditHistoryVo 审核历史接受类
     * @return 1 审核完成、2 还存在下个审核、3 没权限 、4 该人员已审核
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int getSequence(SysAuditHistoryVo sysAuditHistoryVo) throws Exception {
        // long userId = SecurityUtils.getUserId();//当前登录人(当前审核人)
        long userId = sysAuditHistoryVo.getUserId();
        String perms = sysAuditHistoryVo.getPerms();
        //查询按钮id
        long buttonId = sysMenuMapper.getIdByPermissionName(perms);
        long appId = 0;
        int appSize = sysExamineMapper.countAppConfigByButtonId(buttonId);
        if (appSize == 1) {
            //查询按钮id
            appId = sysExamineMapper.selectAppConfigByButtonId(buttonId);
        } else {
            //查询按钮id
            appId = sysExamineMapper.selectOneAppConfigByButtonId(buttonId);
        }
        //根据权限码和单据号 判断是否存在审核节点
        int ins = 0;
        List<SysAppConfigNodeDto> sysList = sysAppConfigNodeMapper.getAppNodeInfo(appId);
        int jie = sysList.size();
        for (int i = 0; i < jie; i++) {
            SysAppConfigNodeDto app = sysList.get(i);
            String id1 = app.getNodeUserId();
            int pp = 0;
            int pp2 = 0;
            if (StringUtils.isEmpty(id1)) {
                pp = 1;
            }
            String[] userNode = id1.split(",");
            String id2 = app.getNodeRoleId();
            if (StringUtils.isEmpty(id2)) {
                pp2 = 1;
            }
            String[] roleIdS = id2.split(",");
            int kl = userNode.length - pp + roleIdS.length - pp2;
            String userStr = String.valueOf(userId);
            //判断是否存在相同的用户id 如果重复 返回4
            int count2 = sysAuditHistoryMapper.countAuditHistory2(app.getNodeId(), sysAuditHistoryVo.getAuditDoc(), perms, userId);
            if (count2 > 0) {
                return 4;
            }
            //判断需要的总条数
            int type = app.getNodeType();
            //需要知道现在审核在什么节点 故需要根据节点循环
            int count = sysAuditHistoryMapper.countAuditHistory(app.getNodeId(), sysAuditHistoryVo.getAuditDoc(), perms);
            sysAuditHistoryVo.setUserId(userId);
            sysAuditHistoryVo.setNodeId(app.getNodeId());
            //一人审核全通过
            if (type == 1) {
                //节点+1
                if (count == 1) {
                    //不是该节点 进入下个节点循环
                    continue;
                } else {//就是当前节点
                    ins = whetherUserTo(userNode, userStr);
                    //记录审核人 并存入审核历史
                    if (ins == 1) {
                        insertAuditHistory(sysAuditHistoryVo);
                        //判断是否还存在下个节点审核
                        //还需要判断存不存在下个节点
                        if (i + 1 == jie) {
                            //1人审核全通过 直接结束
                            return 1;
                        } else {
                            return 2;
                        }
                        //用户信息没有 判断包不包含角色id
                    } else {
                        int bus = whetherRoleTo(roleIdS, userId);
                        if (bus == 0) {
                            //没权限 直接G
                            return 3;
                        } else {
                            //存入审核历史
                            bus = insertAuditHistory(sysAuditHistoryVo);
                            if (bus > 0) {
                                //1人审核全通过 直接结束
                                if (i + 1 == jie) {
                                    return 1;
                                } else {
                                    return 2;
                                }
                            } else {
                                throw new SQLException("抛出异常");
                            }
                        }
                    }
                }
                //需要全部审核
            } else {
                //如果条数相等 证明节点+1
                if (count == kl) {
                    //不是该节点 进入下个节点循环
                    continue;
                    //反之进入当前节点
                } else {
                    //还需要多少审核次数可以结束
                    int up = kl - count;
                    int in = whetherUserTo(userNode, userStr);
                    //包含
                    if (in > 0) {
                        //插入审核历史
                        insertAuditHistory(sysAuditHistoryVo);
                        if (up - 1 == 0) {
                            //结束当前节点 判断是否还存在下个节点
                            if (i + 1 == jie) {
                                //审核完成
                                return 1;
                            } else {
                                return 2;
                            }
                        } else {
                            //当前节点还存在后续审核
                            return 2;
                        }
                        //判断是否含角色信息
                    } else {
                        int jkl = 0;
                        jkl = whetherRoleTo(roleIdS, userId);
                        //包含插入
                        if (jkl > 0) {
                            //存入审核历史
                            int klp = insertAuditHistory(sysAuditHistoryVo);
                            if (klp == 0) {
                                throw new SQLException("抛出异常");
                            }
                            if (up - 1 == 0) {
                                //结束当前节点 判断是否还存在下个节点
                                if (i + 1 == jie) {
                                    //审核完成
                                    return 1;
                                } else {
                                    return 2;
                                }
                            } else {
                                //当前节点还存在后续审核
                                return 2;
                            }
                        } else {
                            return 3;
                        }
                    }
                }
            }
        }
        return 0;
    }

    /**
     * 根据权限码获取审核历史
     */
    @Override
    public List<SysAuditHistoryDto> getAuditHistory(SysAuditHistoryVo sysAuditHistoryVo) {
        return sysAuditHistoryMapper.getAuditHistory(sysAuditHistoryVo);
    }

    /**
     * 修改审核类型
     */
    @Override
    public int updateHistoryAppConfigEdit(SysAuditHistoryVo sysAuditHistoryVo) {
        return sysAuditHistoryMapper.updateHistoryAppConfigEdit(sysAuditHistoryVo);
    }

    /**
     * 新增审核历史
     */
    public int insertAuditHistory(SysAuditHistoryVo sysAuditHistoryVo) {
        if(sysAuditHistoryVo.getAuditState()==2){
            sysAuditHistoryVo.setAuditType(2);
        }
        return sysAuditHistoryMapper.insertAuditHistory(sysAuditHistoryVo);
    }

    /**
     * 判断是否包含角色
     */
    public int whetherRoleTo(String[] roleIdS, long userId) {
        int ins = 0;
        List<Long> roleArr = sysRoleMapper.selectRoleListByUserId(userId);
        if (StringUtils.isEmpty(roleIdS[0])) {
            return ins;
        }
        for (String ro :
            roleIdS) {
            if (roleArr.contains(Long.valueOf(ro))) {
                ins = 1;
                break;
            }
        }
        return ins;
    }

    /**
     * 判断是否包含用户
     */
    public int whetherUserTo(String[] userNode, String str) {
        int ins = 0;
        for (String node :
            userNode) {
            if (node.equals(str)) {//包含id
                ins = 1;
                break;
            }
        }
        return ins;
    }

    /**
     * 解析新增审核信息
     */
    @Transactional(rollbackFor = Exception.class)
    public int theNodeConfig(SysExamine sysExamine){
        int ins = 0;
        long appId = sysExamine.getExamineId();
        JSONArray json = sysExamine.getAuditNodeCode();
        List<SysAppConfigNode> nodeList = JSONArray.parseArray(json.toJSONString(), SysAppConfigNode.class);
        if (nodeList.size() > 0) {
            for (SysAppConfigNode sy :
                nodeList) {
                sy.setExamineId(appId);
                //走节点新增
                ins = sysAppConfigNodeMapper.insertAppConfigNode(sy);
            }
        }
        return ins;
    }

    /**
     * 查询条件
     *
     * @param examine
     * @return Wrapper
     */
    private Wrapper<SysExamine> buildQueryWrapper(SysExamine examine) {
        Map<String, Object> params = examine.getParams();
        QueryWrapper<SysExamine> wrapper = Wrappers.query();
        wrapper
            .like(StringUtils.isNotBlank(examine.getExamineDocName()), "t2.menu_name", examine.getExamineDocName())
            .like(StringUtils.isNotBlank(examine.getExamineCode()), "t1.examine_code", examine.getExamineCode()).between(params.get("beginTime") != null && params.get("endTime") != null,
                "t1.create_time", params.get("beginTime"), params.get("endTime"));
        return wrapper;
    }
}
